#pragma once

#include <vector>
#include <string>

#include <mfapi.h>
#include <mfidl.h>
#include <mfreadwrite.h>
#include <shlwapi.h>
#include "MefoolCOMObjectSharedPtr.h"
#include "MefoolMemoryBuffer.h"

namespace Mefool
{

class DeviceInternals : public IMFSourceReaderCallback
{
public:
	DeviceInternals( const COMObjectSharedPtr<IMFActivate>& activate, const std::string& name );
	virtual ~DeviceInternals();

	class VideoMediaType
	{
	public:
		VideoMediaType();					// Note: put proper accessors here
		UINT32				width ;
		UINT32				height;
		INT32				stride;
		UINT32				frameRate;
		GUID				subType;
				
		std::string			getSubTypeName() const		{ return getSubTypeName(subType); }
		static std::string	getSubTypeName( const GUID& mediaType );

		std::string			toString() const;

		bool				operator==( const DeviceInternals::VideoMediaType& other ) const;
		bool				operator!=( const DeviceInternals::VideoMediaType& other ) const;
	};
	typedef std::vector<VideoMediaType> VideoMediaTypes;
	const VideoMediaTypes&		getSupportedVideoMediaTypes() const { return mSupportedVideoMediaTypes; }

	//bool						startCapture( const VideoMediaType& videoMediaType );
	bool						startCapture( DWORD videoMediaTypeIndex );
	void						stopCapture();
	bool						isCapturing() const	{ return mIsCapturing; }
	//unsigned int				getCapturedImageSequenceNumber() const;
	bool						getCapturedImage( MemoryBuffer& buffer, unsigned int& sequenceNumber, LONGLONG& timestamp ) const;

protected:
	static bool					getVideoMediaType( IMFSourceReader* sourceReader, DWORD index, VideoMediaType& mediaTypeInfo );
	static VideoMediaTypes		getVideoMediaTypes( IMFSourceReader* sourceReader );
	bool						createMediaSourceReader();
	void						deleteMediaSourceReader();

	STDMETHODIMP				QueryInterface( REFIID riid, void** ppv );
	STDMETHODIMP_(ULONG)		AddRef();
	STDMETHODIMP_(ULONG)		Release();
	STDMETHODIMP				OnReadSample( HRESULT hrStatus, DWORD dwStreamIndex, DWORD dwStreamFlags, LONGLONG llTimestamp, IMFSample *pSample);
	STDMETHODIMP				OnEvent( DWORD, IMFMediaEvent* );
	STDMETHODIMP				OnFlush( DWORD );
	
private:
	COMObjectSharedPtr<IMFActivate>	mActivate;			
	std::string					mName;
	mutable CRITICAL_SECTION	mCriticalSection;
	ULONG						mReferenceCounter;
	COMObjectSharedPtr<IMFSourceReader> mSourceReaderRes;
	bool						mIsCapturing;
	VideoMediaTypes				mSupportedVideoMediaTypes;
	unsigned int				mCapturedImageNumber;
	LONGLONG					mCapturedImageTimestamp;
	MemoryBuffer*				mCapturedImageBuffer;
};

}
